home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Magnum One
/
Magnum One (Mid-American Digital) (Disc Manufacturing).iso
/
d12
/
advancec.arc
/
WINDOW.C
< prev
Wrap
C/C++ Source or Header
|
1992-01-24
|
22KB
|
922 lines
/*
window.c
window manager functions and variables
*/
#include "usrif.h"
#undef NULL
#ifdef TRUE #undef TRUE #endif
#ifdef FALSE #undef FALSE #endif
#include <stdio.h>
/* window management variables */
static window_t *front, *back;
int num_windows = 0;
/* globals */
extern seg_t *desk_seg;
extern rect_t screen;
/* minimum window size */
#define MIN_WX 100
#define MIN_WY 70
/* viewport for window manager */
vport_t *the_port = NULL;
/* base rectangle for new_rect() */
rect_t base_rect;
/* new window size */
#define HSIZE 400
#define VSIZE 300
/* offsets for new window */
#define HDEL 50
#define VDEL 50
#define VBASE (screen.top-VSIZE-VDEL)
#define HBASE HDEL
/* new window rectangle, offset variables */
int hdir = HDEL, vdir = 0-HDEL;
/*
window manager initialization function
init_window()
called to reset window list,
also creates and draws the
desktop segment
*/
init_window()
{
vport_t *new_vport();
front = back = NULL;
num_windows = 0;
/* make primary viewport */
the_port = new_vport(&screen);
/* map to entire screen */
the_port->window = &screen;
/* make desktop segment */
make_desktop();
draw_seg(desk_seg, the_port);
/* set first window place and size */
set_rect(&base_rect,
HBASE, VBASE, HBASE+HSIZE, VBASE+VSIZE);
}
/*
window creation functions
new_window( name, segment, rect )
instantiates a new window structure,
creates the window shape segment
to correspond with name and rect,
links window into window list,
draws new window,
and returns a pointer to new window
new_rect()
creates new window rectangle,
offset from last time
new_rect() was called
*/
window_t *new_window( name, segment, rect )
char *name;
seg_t *segment;
rect_t *rect;
{
window_t *new;
key_t *mykey, *inst_key();
rect_t *inst_rect(), *new_rect(), *copy_rect();
text_t *inst_text();
void view_window();
num_windows++;
if(num_windows > MAX_WINDOWS)
return(NULL);
if(new = CALLOC( 1, window_t))
{
new->name = name;
/* check for minimum window size */
if( (rect->right - rect->left) < MIN_WX)
rect->right = rect->left + MIN_WX;
if( (rect->top - rect->bottom) < MIN_WY)
rect->top = rect->bottom + MIN_WY;
/* get new window rectangle */
new->area = rect;
/* make title area rectangle */
new->title = inst_rect(
new->area->left + 2,
new->area->top - 20,
new->area->right - 2,
new->area->top - 2);
/* make data area rectangle */
new->pane = inst_rect(
new->area->left + 1,
new->area->bottom + 1,
new->area->right - 1,
new->area->top - 22);
/* make segment for window */
cr_seg( name );
add_attr(RESET);
/* fill shape background */
add_attr(FILL);
add_rect(copy_rect(new->area));
add_attr(NOFILL);
/* frame shape background */
add_attr(FRAME);
add_attr(BLACK);
add_rect(copy_rect(new->area));
/* fill window title area */
add_attr(FILL);
add_attr(BLACK);
add_rect(copy_rect(new->title));
add_attr(WHITE);
text(name,
new->title->left + 8,
new->title->bottom + 5,
LEFT , BOTTOM);
new->shape = cl_seg();
new->data = segment;
new->data_win = copy_rect(segment->bbox);
draw_win( new );
/* link to top of window list */
/* no windows exist */
if(front == NULL)
back = front = new;
/* some windows exist */
else {
/* make new window the front window */
front->prev = new;
new->next = front;
new->prev = NULL;
front = new;
}
}
else
error("can't create new window");
/* set up window customer */
new->button_fn = &view_window;
return(new);
}
rect_t *new_rect()
{
rect_t r, *n, *copy_rect();
int p;
/* copy current base window rectangle */
n = copy_rect(&base_rect);
offset_rect(&base_rect, hdir, vdir);
/* move base rectangle to new position */
if( base_rect.right > screen.right)
{
p = base_rect.bottom;
set_rect(&base_rect,HBASE,p,HBASE+HSIZE,p+VSIZE);
}
if( base_rect.bottom < screen.bottom)
{
p = base_rect.left;
set_rect(&base_rect,p,VBASE,p+HSIZE,VBASE+VSIZE);
}
return(n);
}
/*
window pop function
pop_window(window)
makes given window the
top, or active, window
*/
pop_window( window )
window_t *window;
{
/* already on top? */
if(window == front)
return;
/* relink to top */
if(window == back)
{
/* window is bottom one */
window->prev->next = NULL;
back = window->prev;
}
else /* not front or back */
{
window->prev->next = window->next;
window->next->prev = window->prev;
}
front->prev = window;
window->next = front;
window->prev = NULL;
front = window;
/* draw window */
draw_win(window);
}
/*
window detection functions
front_window()
returns window pointer to
active, or front, window
what_window( where )
returns pointer to
top window that the point
where is in, else NULL
in_window( point, window)
in_title( point, window)
in_pane( point, window)
these return TRUE if point
is in the region, else FALSE
*/
window_t *front_window()
{
return(front);
}
window_t *what_window( where )
point_t *where;
{
window_t *mywin, *inwin;
inwin = NULL;
mywin = back;
while(mywin != NULL)
{
if(in_window( where, mywin ))
inwin = mywin;
/* next higher window */
mywin = mywin->prev;
}
return(inwin);
}
in_window( point, window)
point_t *point;
window_t *window;
{
if(pt_in_rect( window->area, point))
return(TRUE);
return(FALSE);
}
in_title( point, window)
point_t *point;
window_t *window;
{
if(pt_in_rect( window->title, point))
return(TRUE);
return(FALSE);
}
in_pane( point, window)
point_t *point;
window_t *window;
{
if(pt_in_rect( window->pane, point))
return(TRUE);
return(FALSE);
}
/*
window menu control functions
mod_window( event, window )
queries user for window modification
for the active window, then performs
selected modification operation
view_window( event, window )
queries user for view operation
for active window, then performs
selected view operation
*/
/* operation selection menu item definitions */
#define CANCEL 0
#define MOVE 1
#define SIZE 2
#define CLOSE 3
/* window modify operation selection menu items */
char *mod_ops[4] =
{
"Cancel",
"Move",
"Size",
"Close"
};
mod_window( event, window )
event_t *event;
window_t *window;
{
int sel;
rect_t *old_rect, *copy_rect();
/* pops up menu, user selects item */
sel = pop_up_menu( 4, mod_ops );
/* which item was selected? */
switch(sel)
{
case CANCEL :
/* user decided not to modify */
return;
case MOVE :
/* animate window move */
{
point_t first, last, delta;
key_t *key;
/* copy window bounds */
old_rect = copy_rect(window->area);
get_cursor(&first);
xor_rect(window->area,FRAME);
/* animate window outline */
while(event->what != DN_BUTTON_EVENT)
{
get_cursor(&last);
event = get_next_event();
delta.x = event->where.x - last.x;
delta.y = event->where.y - last.y;
if( delta.x != 0 || delta.y != 0)
{
/* remove old outline */
xor_rect(window->area,FRAME);
/* set new outline */
offset_rect(window->area, delta.x, delta.y);
/* add new outline */
xor_rect(window->area,FRAME);
}
}
/* found new window size */
xor_rect(window->area,FRAME);
/* calculate window's change in position */
delta.x = event->where.x - first.x;
delta.y = event->where.y - first.y;
/* offset window's regions */
offset_rect(window->title, delta.x, delta.y);
offset_rect(window->pane, delta.x, delta.y);
offset_rect(window->shape->bbox, delta.x, delta.y);
/* offset window's shape segment */
key = window->shape->data;
while(key != NULL)
{
switch(key->type)
{
case RECT :
offset_rect(key->key.rect, delta.x, delta.y);
break;
case TEXT :
key->key.text->origin.x += delta.x;
key->key.text->origin.y += delta.y;
break;
}
key = key->next;
}
/* refresh bit map */
all_wins( old_rect );
free(old_rect);
draw_win( window );
}
break;
case SIZE :
/* animate window sizing */
{
point_t first, last, delta;
key_t *key;
/* copy window bounds */
old_rect = copy_rect(window->area);
first.x = window->area->right;
first.y = screen.top - window->area->bottom;
set_cursor(&first);
first.y = window->area->bottom;
xor_rect(window->area,FRAME);
/* animate window outline */
while(event->what != DN_BUTTON_EVENT)
{
get_cursor(&last);
event = get_next_event();
if(event->where.x < (window->area->left + MIN_WX))
delta.x = 0;
else
delta.x = event->where.x - last.x;
if(event->where.y > (window->area->top - MIN_WY))
delta.y = 0;
else
delta.y = event->where.y - last.y;
if( delta.x != 0 || delta.y != 0)
{
/* remove old outline */
xor_rect(window->area,FRAME);
/* set new outline */
window->area->right += delta.x;
window->area->bottom += delta.y;
/* add new outline */
xor_rect(window->area,FRAME);
}
}
/* found new window size */
xor_rect(window->area,FRAME);
/* calculate window's change in position */
delta.x = window->area->right - first.x;
delta.y = window->area->bottom - first.y;
/* offset window's regions */
window->title->right += delta.x;
window->pane->right += delta.x;
window->pane->bottom += delta.y;
window->shape->bbox->right += delta.x;
window->shape->bbox->bottom += delta.y;
/* redo window's shape segment
to reflect new size */
key = window->shape->data;
while(key != NULL)
{
if(key->type == RECT)
{
if(key->key.rect->bottom == window->title->bottom)
/* do not change title bottom */
key->key.rect->right += delta.x;
else
{
key->key.rect->right += delta.x;
key->key.rect->bottom += delta.y;
}
}
key = key->next;
}
/* refresh bit map */
all_wins( old_rect );
free(old_rect);
draw_win( window );
}
break;
case CLOSE :
/* remove window */
purge_window( window);
/* refresh */
all_wins( window->area );
break;
}
/* refresh display */
}
/* window view operation selection menu items */
#define REDUCE 1
#define ENLARGE 2
#define SCROLL 3
#define FIT 4
char *view_ops[5] =
{
"Cancel",
"Reduce",
"Enlarge",
"Scroll",
"Fit"
};
/* scroll operation types */
#define S_UP 0
#define S_LEFT 1
#define S_RIGHT 2
#define S_DOWN 3
char *scroll_ops[4] =
{
"Up",
"Left",
"Right",
"Down"
};
void view_window(event, window)
event_t *event;
window_t *window;
{
int sel, zoom, pan, h, w;
rect_t *copy_rect();
/* pop up view modify menu, user selects item */
sel = pop_up_menu( 5, view_ops );
switch(sel)
{
case CANCEL :
break;
case REDUCE :
h = window->data_win->right - window->data_win->left;
w = window->data_win->top - window->data_win->bottom;
zoom = h > w ? h/10 : w/10;
inset_rect(window->data_win, -zoom, -zoom);
draw_win(window);
break;
case ENLARGE :
h = window->data_win->right - window->data_win->left;
w = window->data_win->top - window->data_win->bottom;
zoom = h < w ? h/10 : w/10;
inset_rect(window->data_win, zoom, zoom);
draw_win(window);
break;
case SCROLL :
/* pop up scroll menu, user selects item */
sel = pop_up_menu( 4, scroll_ops );
h = window->data_win->right - window->data_win->left;
w = window->data_win->top - window->data_win->bottom;
switch(sel)
{
case S_LEFT :
pan = h / 3;
offset_rect(window->data_win, pan, 0);
break;
case S_RIGHT :
pan = h / 3;
offset_rect(window->data_win, -pan, 0);
break;
case S_UP :
pan = w / 3;
offset_rect(window->data_win, 0, -pan);
break;
case S_DOWN :
pan = w / 3;
offset_rect(window->data_win, 0, pan);
break;
}
/* do scroll */
draw_win( window );
break;
case FIT :
free(window->data_win);
window->data_win = copy_rect(window->data->bbox);
draw_win(window);
break;
}
}
/*
window drawing functions
draw_win(window)
draws given window
draw_all()
draws desktop, then all windows
from back to front
*/
draw_win( window )
window_t *window;
{
vport_t winport;
rect_t tr;
union_rect(&screen,window->area,&tr);
if( equal_rect(&screen, &tr) == FALSE)
{
win_inrect( window, window->area );
return;
}
/* hide cursor */
hide_cursor();
/* draw window's shape segment */
draw_seg(window->shape, the_port);
if(window->data != NULL)
{
/* set up viewport for window's data segment */
winport.bitmap = window->pane;
winport.window = window->data_win;
winport.seg = window->data;
/* draw window's data segment */
draw_seg(window->data, &winport);
}
/* show cursor */
show_cursor();
}
draw_all()
{
window_t *mywin;
/* hide cursor */
hide_cursor();
draw_seg(desk_seg, the_port);
mywin = back;
while(mywin != NULL)
{
draw_win(mywin);
/* next higher window */
mywin = mywin->prev;
}
/* show cursor */
show_cursor();
}
all_wins( inrect )
rect_t *inrect;
{
window_t *mywin;
vport_t winport;
/* hide cursor */
hide_cursor();
/* add small border */
inset_rect( inrect, -1, -1);
winport.bitmap = inrect;
winport.window = inrect;
draw_seg( desk_seg, &winport);
mywin = back;
while(mywin != NULL)
{
win_inrect( mywin, inrect );
/* next higher window */
mywin = mywin->prev;
}
inset_rect(inrect,1,1);
/* show cursor */
show_cursor();
}
/*
refresh window in rectangle
*/
win_inrect( window, rect )
window_t *window;
rect_t *rect;
{
vport_t winport;
double nl, nb, nr, nt, /* normalized display coordinates */
pw, ph; /* width and height */
rect_t sr, pr, wr, tpr, twr; /* screen, port, and window rect */
rect_t *copy_rect();
/* hide cursor */
hide_cursor();
/* clip draw rect to screen */
sect_rect(&screen, rect, &sr);
/* set up viewport for window's data segment */
winport.bitmap = copy_rect(&sr);
offset_rect(winport.bitmap, -1, 0);
winport.window = &sr;
/* draw window's shape segment */
draw_seg(window->shape, &winport);
free(winport.bitmap);
if(window->data != NULL)
{
if(clip_map( window->pane, window->data_win, &sr, &pr, &wr))
{
winport.bitmap = ≺
winport.window = ≀
/* draw window's data segment */
draw_seg(window->data, &winport);
}
}
/* show cursor */
show_cursor();
}
/*
clip map takes viewport bounds,
clipping window, and clipping rectangle
as arguments; then returns new
viewport bounds and clipping window
*/
clip_map( old_port, old_win, clip_rect, new_port, new_win)
rect_t *old_port,
*old_win,
*clip_rect,
*new_port,
*new_win;
{
double nl, nb, nr, nt, /* normalized display coords */
pw, ph; /* width and height */
if(sect_rect(clip_rect, old_port, new_port))
{
pw = (double) (old_port->right - old_port->left);
ph = (double) (old_port->top - old_port->bottom);
/* These must never be equal to 0.0! */
/* convert clipped port to normalized display coordinates */
nl = ((double) (new_port->left - old_port->left)) / pw;
nr = ((double) (new_port->right - old_port->left)) / pw;
nb = ((double) (new_port->bottom - old_port->bottom)) / ph;
nt = ((double) (new_port->top - old_port->bottom)) / ph;
/* find new window */
pw = (double) (old_win->right - old_win->left);
ph = (double) (old_win->top - old_win->bottom);
if(nl == 0.0)
new_win->left = old_win->left;
else
new_win->left = old_win->left + (int) ( nl * pw );
if(nb == 0.0)
new_win->bottom = old_win->bottom;
else
new_win->bottom = old_win->bottom + (int) ( nb * ph );
if(nr == 1.0)
new_win->right = old_win->right;
else
new_win->right = old_win->left + (int) ( nr * pw );
if(nt == 1.0)
new_win->top = old_win->top;
else
new_win->top = old_win->bottom + (int) ( nt * ph );
return(TRUE);
}
else
return(FALSE);
}
/*
window removal functions
purge_window(window)
removes given window from
linked window list
purge_all()
resets window list to be empty
Note:
both functions call draw_all()
*/
purge_window(window)
window_t *window;
{
/*
remove from doubly linked list
remove window shape segment
free window structure from memory
Note:
Only the front or active window
can be purged.
This does not free the window structure
or its associated data from memory!
*/
if(window == back)
/* last window in list */
front = back = NULL;
else
{
front->next->prev = NULL;
front = front->next;
}
window->next = window->prev = NULL;
num_windows--;
}
purge_all()
{
/*
remove all windows
Note:
This does not free window structures
or their associated data from memory!
*/
front = back = NULL;
draw_all();
num_windows = 0;
}